package com.yuanchu.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.yuanchu.common.utils.PageResult;
import com.yuanchu.search.client.FeignGoodsClient;
import com.yuanchu.search.dto.QueryGoodsList;
import com.yuanchu.search.dto.QueryGoodsParamsDto;
import com.yuanchu.search.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @version: 1.0
 * @Author: adan
 * @description:
 * @date: 2024-03-11 18:04
 */
@Service
@Slf4j
public class GoodsServiceImpl implements GoodsService {
    @Resource
    private RestHighLevelClient client;
    @Resource
    private FeignGoodsClient feignGoodsClient;
    @Override
    public PageResult<QueryGoodsList> queryGoodsList(QueryGoodsParamsDto param) {
        Integer page = param.getPage();
        Integer pageSize = param.getPageSize();
        String goodsNo = param.getGoodsNo();
        String goodsName = param.getGoodsName();
        Integer categoryId = param.getCategoryId();
        String listType = param.getListType();
        // 设置索引
        SearchRequest searchRequest = new SearchRequest("yuanchu_goods");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 构建条件查询
        BoolQueryBuilder boolQueryBuilder = buildBasicQuery( goodsNo, goodsName, categoryId, listType);

        // 分页
        Integer pageNo = page;
        int start = (pageNo - 1) * pageSize;
        searchSourceBuilder.from(start);
        searchSourceBuilder.size(Math.toIntExact(pageSize));

        // 布尔查询
        searchSourceBuilder.query(boolQueryBuilder);
                // .sort(SortBuilders.fieldSort("goodsPriceMin.keyword").order(SortOrder.DESC));
        // sortType: sales
        // sortType: price
        // sortPrice: 0 升序
        // sortPrice: 1 降序
        String sortType = param.getSortType();
        Integer sortPrice = param.getSortPrice();
        if (StringUtils.isNotEmpty(sortType)){
            if ("sales".equals(sortType)){
                searchSourceBuilder.sort(SortBuilders.fieldSort("salesActual").order(SortOrder.DESC));
            }else if ("price".equals(sortType)){
                if (sortPrice == 0){
                    searchSourceBuilder.sort(SortBuilders.fieldSort("goodsPriceMin.keyword").order(SortOrder.ASC));
                }else if (sortPrice == 1){
                    searchSourceBuilder.sort(SortBuilders.fieldSort("goodsPriceMin.keyword").order(SortOrder.DESC));
                }
            }
        }else {
            searchSourceBuilder.sort(SortBuilders.fieldSort("sort").order(SortOrder.DESC));
        }
        // goodsPriceMin.keyword
        // salesActual
        // 请求搜索
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("搜索异常：{}", e.getMessage());
            return PageResult.formatPageResult(Collections.emptyList(), pageNo, pageSize);
        }

        // 结果集处理
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        // 记录总数
        TotalHits totalHits = hits.getTotalHits();
        // 数据列表
        List<QueryGoodsList> list = new ArrayList<>();

        for (SearchHit hit : searchHits) {
            String sourceAsString = hit.getSourceAsString();
            QueryGoodsList goodsList = JSON.parseObject(sourceAsString, QueryGoodsList.class);
            list.add(goodsList);
        }
        return PageResult.formatPageResult(list, pageNo, pageSize, totalHits.value);
    }

    private BoolQueryBuilder buildBasicQuery(String goodsNo, String goodsName, Integer categoryId, String listType) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 关键字
        if (StringUtils.isNotEmpty(listType)) {
            // 搜索类型
            switch (listType) {
                case "on_sale":
                    boolQueryBuilder.must(QueryBuilders.matchQuery("status", 10));
                    break;
                case "off_sale":
                    boolQueryBuilder.must(QueryBuilders.matchQuery("status", 20));
                    break;
                case "sold_out":
                    boolQueryBuilder.must(QueryBuilders.matchQuery("stockTotal", 0));
                    break;
                default:
                    break;
            }
        }
        if (StringUtils.isNotEmpty(goodsNo)) {
            // 搜索类型
            boolQueryBuilder.must(QueryBuilders.matchQuery("goodsNo", goodsNo));
        }
        if (StringUtils.isNotEmpty(goodsName)) {
            // 搜索类型
            boolQueryBuilder.must(QueryBuilders.matchQuery("goodsName", goodsName));
        }
        // if (categoryId != null && categoryId > 0) {
        //     List<Integer> goodsIds = feignGoodsClient.queryByGoodsIds(categoryId);
        //     if (!goodsIds.isEmpty()) {
        //         boolQueryBuilder.must(QueryBuilders.termsQuery("goodsId", goodsIds.toArray(new Long[0])));
        //     }
        // }
        if (categoryId != null && categoryId > 0) {
            // 分类查询
            List<Integer> goodsIds = feignGoodsClient.queryByGoodsIds(categoryId);
            if (!goodsIds.isEmpty()) {
                BoolQueryBuilder goodsIdQuery = QueryBuilders.boolQuery();
                for (Integer goodsId : goodsIds) {
                    goodsIdQuery.should(QueryBuilders.termQuery("goodsId", goodsId));
                }
                boolQueryBuilder.must(goodsIdQuery);
            }
        }
        return boolQueryBuilder;
    }
}
